﻿using Kinlo.Entitys;
using Kinlo.MESDocking;
using NewLife;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using UIWindows.GlobalStatics;
using UIWindows.Tools.Helper;
using XingLucifer.Devices;
using XingLucifer.IBase;
using XingLucifer.IBase.Enums;
using XingLucifer.IBase.Models.PLCInteraktion;

namespace UIWindows.Services
{
    public abstract class ServierBase
    {
        protected IMESInteraction _interaction;
        protected DeviceConfigStatic _deviceConfig;
        protected SystemConfigStatic _systemConfig;
        protected UserConfigStatic _userConfig;
        protected ParameterStatic _parameterStatic;
        protected MesParameterStatic _mesParameterStatic;
        protected TemporaryStatic _temporaryStatic;
        protected HomeStatic _homeStatic;

        public ServierBase(DeviceConfigStatic deviceConfig, SystemConfigStatic systemConfig,
            UserConfigStatic userConfig, ParameterStatic parameterStatic,
            TemporaryStatic temporaryStatic, HomeStatic homeStatic, MesParameterStatic mesParameterStatic)
        {
            _deviceConfig = deviceConfig;
            _systemConfig = systemConfig;
            _userConfig = userConfig;
            _parameterStatic = parameterStatic;
            _temporaryStatic = temporaryStatic;
            _homeStatic = homeStatic;
            _mesParameterStatic = mesParameterStatic;
        }

        protected Context.DataContext _context;
        public virtual Task Handle(Context.DataContext context)
        {
            int count = 0;
            var plc = _deviceConfig.DeviceList.FirstOrDefault(x => x.ServiceName == context.ServiceName && x.TaskType == TaskTypes.扫描信号);
            if (plc != null)
            {
                OmronCIP omronCIP = plc.Communication as OmronCIP;
                while (count < 3)
                {
                    if (omronCIP.WriteSingle((short)2, context.Address_Signal))
                    {
                        RunLog($"启动地址{context.Address_Signal} 置2 成功", MessageLevelType.信息);
                        break;
                    }
                    else
                    {
                        RunLog($"启动地址{context.Address_Signal} 置2 失败", MessageLevelType.警告);
                    }
                    count++;
                }
            }
            TaskService.Instance.RemoveTask(context);
            RunLog("结束任务", MessageLevelType.信息);
            return Task.CompletedTask;
        }

        protected bool ClearSignal(Context.DataContext context)
        {
            if (_context == null)
            {
                _context = context;
            }
            RunLog("收到PLC信号", MessageLevelType.信息);
            var plc = _deviceConfig.DeviceList.FirstOrDefault(x => x.ServiceName == context.ServiceName && x.TaskType == TaskTypes.扫描信号);
            if (plc != null)
            {
                try
                {
                    OmronCIP omronCIP = plc.Communication as OmronCIP;
                    if (omronCIP.WriteSingle((short)99, context.Address_Signal))
                    {
                        RunLog("启动地址 置99 成功", MessageLevelType.信息);
                        return true;
                    }
                    else
                    {
                        RunLog("启动地址 置99 失败", MessageLevelType.警告);
                    }
                }
                catch (Exception)
                {
                    Thread.Sleep(500);
                    return false;
                }
            }
            Thread.Sleep(500);
            return false;
        }

        protected void RunLog(string info, MessageLevelType levelType = MessageLevelType.信息, Context.DataContext context = default)
        {
            if (context != null)
            {
                _context = context;
            }
            if (_context == null)
            {
                return;
            }
            $"[{_context.ServiceName}]-[{_context.TaskType}]-[{_context.DeviceType}]：{info}".RunLog(levelType);
        }

        /// <summary>
        /// 扫码枪通用扫码方法
        /// </summary>
        /// <param name="scancode_count">重复扫码次数</param>
        /// <param name="devices">扫码枪设备</param>
        /// <param name="index">设备序号</param>
        /// <param name="barcodeNumber">条码数量</param>
        /// <param name="barcode_length">扫码枪返回的长度</param>
        /// <param name="isBattery">是否是电池码， true 是  false 否（托盘扫码）</param>
        /// <returns></returns>
        public string ScanCode(int scancode_count, IDevices devices, int index, bool isBattery = true, int barcodeNumber = 1, int barcode_length = 1024)
        {
            List<string> barcodeList = new List<string>();
            for (int i = 0; i <= scancode_count; i++)
            {
                barcodeList.Clear();
                string? barcode = devices.ReadSingle<string>(0, barcode_length);
                RunLog($"-[{index}] 扫码枪返回：{barcode}");
                if (barcodeNumber > 1)
                {
                    string[] barcodes = barcode.Split(',');
                    if (barcodes.Length < barcodeNumber)
                    {
                        barcodeList = Enumerable.Repeat("ERROR", barcodeNumber).ToList();
                        RunLog($"-[{index}] 扫码枪{barcode}条码个数和需要个数{barcodeNumber}不符");
                    }
                    else
                    {
                        for (int k = 0; k < barcodeNumber; k++)
                        {
                            string barcode1 = System.Text.RegularExpressions.Regex.Match(barcodes[k], isBattery ? _systemConfig.SCM.BarcodeRules : _systemConfig.SCM.CupCodeRules, System.Text.RegularExpressions.RegexOptions.Compiled).Value;
                            RunLog($"-[{index}] 位置:[{k + 1}] 校验后:[{barcode1}]");
                            barcodeList.Add($"{(string.IsNullOrEmpty(barcode1) ? "ERROR" : barcode1)}");
                        }
                    }
                }
                else
                {
                    string barcode1 = System.Text.RegularExpressions.Regex.Match(barcode, isBattery ? _systemConfig.SCM.BarcodeRules : _systemConfig.SCM.CupCodeRules, System.Text.RegularExpressions.RegexOptions.Compiled).Value;
                    RunLog($"-[{index}] 校验后:[{barcode1}]");
                    barcodeList.Add($"{(string.IsNullOrEmpty(barcode1) ? "ERROR" : barcode1)}");
                }
                if (!barcodeList.Any(x => x == "ERROR")) break;
                Thread.Sleep(_parameterStatic.RunParameter.IntervalTime_ScanCode);
            }
            string resutBarcode = barcodeList.Join("_");
            return resutBarcode;
        }

        /// <summary>
        /// 写入注液量至PLC
        /// </summary>
        /// <param name="value_inj"></param>
        /// <param name="plc"></param>
        /// <param name="label"></param>
        /// <param name="context"></param>
        /// <returns></returns>
        public bool WriteInjectionVolume(float value_inj, OmronCIP plc, string label, Context.DataContext context)
        {
            for (int i = 1; i < 4; i++)
            {
                // if (plc.WriteSingle(value_inj, $"{label}.face.PCData"))
                if (plc.WriteSingle(value_inj, $"{label}.face.PCData"))
                {
                    RunLog($"第[{i}]次 注液量 [{value_inj:F2}] 写入成功", MessageLevelType.信息);
                    return true;
                }
                else
                {
                    RunLog($"第[{i}]次 注液量 [{value_inj:F2}] 写入失败", MessageLevelType.警告);
                }
            }
            return false;
        }
        /// <summary>
        /// 注液范围检查
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="Index">1:后称，2：补液称</param>
        /// <returns></returns>
        public ResultTypes InjRange_Check(ProductionData entity, int index)
        {
            string[] range = entity.RangeFluidRate.Split('-');
            double down_inj = Convert.ToDouble(range[0]);
            double standard = Convert.ToDouble(range[1]);
            double up_inj = Convert.ToDouble(range[2]);

            range = entity.RangeAfterWeighing.Split('-');
            double down_weiging = Convert.ToDouble(range[0]);
            double up_weiging = Convert.ToDouble(range[1]);

            entity.TotalInjectionVolumeDeviationValue = Math.Round(entity.ActualTotalInjectionVolume - standard, 2, MidpointRounding.AwayFromZero);

            var weighting = index == 1 ? entity.AfterWeighing : entity.RehydrationWeighing;
            ResultTypes types = (weighting, entity.ActualTotalInjectionVolume) switch
            {
                var k when k.weighting <= up_weiging && k.weighting >= down_weiging && k.ActualTotalInjectionVolume <= up_inj && k.ActualTotalInjectionVolume >= down_inj => ResultTypes.合格,
                var k when k.weighting > up_weiging => ResultTypes.称重偏重,
                var k when k.weighting < down_weiging => ResultTypes.称重偏轻,
                var k when k.ActualTotalInjectionVolume > up_inj => ResultTypes.注液量偏多,
                var k when k.ActualTotalInjectionVolume < down_inj => ResultTypes.注液量偏少,
                _ => ResultTypes.不合格,
            };

            if (!_parameterStatic.DecideParameter.EnableAfterInjection && (types == ResultTypes.称重偏轻 || types == ResultTypes.称重偏重))
            {
                RunLog($"请注意!!![{entity.BarCode}] 未启用后称重检查==>>强制合格");
                return ResultTypes.合格;
            }
            if (!_parameterStatic.DecideParameter.EnableLiquidInjectionRange && (types == ResultTypes.注液量偏多 || types == ResultTypes.注液量偏少))
            {
                RunLog($"请注意!!![{entity.BarCode}] 未启用注液量检查==>>强制合格");
                return ResultTypes.合格;
            }
            return types;
        }
        /// <summary>
        /// 写入结果
        /// </summary>
        /// <param name="barCode">条码</param>
        /// <param name="resultTypes">结果</param>
        /// <param name="devices">设备链接</param>
        /// <param name="address">地址</param>
        /// <param name="context">上下文</param>
        public void WriteResult(string barCode, ResultTypes resultTypes, OmronCIP devices, string label, Context.DataContext context)
        {
            short ng_type = 0;
            string code = string.Empty;
            if (!string.IsNullOrEmpty(barCode))
            {
                code = "条码：" + barCode;
            }

            switch (resultTypes)
            {
                case ResultTypes._:
                case ResultTypes.合格: ng_type = 1; break;
                default:
                case ResultTypes.注液量发送失败:
                case ResultTypes.不合格:
                case ResultTypes.扫码NG: ng_type = 2; break;
                case ResultTypes.注液量不匹配:
                case ResultTypes.MES_NG:
                case ResultTypes.记忆跟踪NG: ng_type = 3; break;
                case ResultTypes.注液量偏多: ng_type = 4; break;
                case ResultTypes.注液量偏少: ng_type = 5; break;
                case ResultTypes.测漏NG: ng_type = 6; break;
            }

            for (int i = 1; i < 4; i++)
            {
                if (devices.WriteSingle(ng_type, $"{label}.PCResult"))
                {
                    RunLog($"第[{i}]次 {code}， 结果 [{ng_type}] 写入成功", MessageLevelType.信息);
                    return;
                }
                else
                {
                    RunLog($"第[{i}]次 {code}，结果 [{ng_type}] 写入失败", MessageLevelType.警告);
                }
            }
        }
        /// <summary>
        /// 写注液量至注液泵
        /// </summary>
        /// <param name="value"></param>
        /// <param name="address"></param>
        /// <param name="device"></param>
        /// <returns></returns>
        public bool SendInj(double value, int address, Models.Devices.DeviceClientModel device)
        {
            for (int i = 0; i < 3; i++)
            {
                switch (device.DeviceType)
                {
                    case DeviceTypes.NJ_FINS_PLC:
                    case DeviceTypes.NX_FINS_PLC:
                        #region 精朗泵
                        ushort inj_I = (ushort)(value * 100);
                        if (device.Communication.WriteSingle(inj_I, address, 0, 0))
                        {
                            return inj_I == device.Communication.ReadSingle<ushort>(address, 0);
                        }
                        #endregion
                        break;
                    case DeviceTypes.Modbus_TCP_DCBA:
                        float inj = (float)value;
                        //if (device.Communication.WriteSingle(inj, 7050, 0, 0))
                        if (device.Communication.WriteSingle(inj, address, 0, 0))
                        {
                            var defultInf = device.Communication.ReadSingle<float>(address, 0);
                            //  RunLog($"写入注液量为：{inj};读取泵内注液量为：{defultInf}", MessageLevelType.警告);
                            return inj == defultInf;
                        }
                        break;
                }
                Thread.Sleep(200);
            }
            return false;
        }

        /// <summary>.
        /// 写入指令
        /// </summary>
        /// <param name="value">值</param>
        /// <param name="devices">PLC链接</param>
        /// <param name="address">地址</param>
        public void WriteCMD(short value, OmronCIP plc, string label)
        {
            for (int i = 1; i < 4; i++)
            {
                if (plc.WriteSingle(value, label))
                {
                    RunLog($"第[{i}]次 命令 [{value}] 写入成功", MessageLevelType.信息);
                    return;
                }
                else
                {
                    RunLog($"第[{i}]次 命令 [{value}] 写入失败", MessageLevelType.警告);
                }
            }
        }

        /// <summary>
        /// 读取记忆
        /// </summary>
        /// <param name="devices">链接设备</param>
        /// <param name="address_struct">结构体起始地址</param>
        /// <param name="struct_length">结构体长度</param>
        /// <param name="alarm_address">报警地址</param>
        /// <returns></returns>
        public (bool, List<BatteryDataModel>) ReadErinnerungen(OmronCIP devices, string address_struct, int struct_length, string alarm_address, string method)
        {
            BatteryArrayModel batteryArray = new BatteryArrayModel(struct_length);
            try
            {
                for (int i = 0; i < 3; i++)
                {
                    devices.ReadClass(address_struct, batteryArray);
                    List<BatteryDataModel> batteryDatas = new List<BatteryDataModel>();
                    for (int j = 0; j < batteryArray.Batterys.Length; j++)
                    {
                        if (batteryArray.Batterys[j].ID != 0)
                        {
                            batteryDatas.Add(new BatteryDataModel()
                            {
                                Index = (byte)(j + 1),
                                Address_Struct = $"{address_struct}[{j}]",
                                SnowflakeId = batteryArray.Batterys[j].ID,
                                Data_PLC = batteryArray.Batterys[j].Data_PLC,
                                Results_PLC = batteryArray.Batterys[j].Results_PLC
                            });
                        }
                    }
                    if (batteryDatas.Count > 0)
                    {
                        return new(false, batteryDatas);
                    }
                    if (i == 2 && batteryDatas.Count == 0)
                    {
                        WriteCMD(1, devices, alarm_address);
                    }
                    Thread.Sleep(500);
                }
            }
            catch (Exception e)
            {
                RunLog($"读取记忆异常：{e}");
            }
            return new(true, default);
        }


      
        /// <summary>
        /// 读取单个记忆
        /// </summary>
        /// <param name="devices">链接设备</param>
        /// <param name="address_struct">结构体起始地址</param>
        /// <param name="struct_length">结构体长度</param>
        /// <param name="alarm_address">报警地址</param>
        /// <returns></returns>
        public (bool, BatteryDataModel) ReadOneErinnerungen(OmronCIP devices, string address_struct, int struct_length, string alarm_address, string method)
        {
            BatteryArrayModel batteryArray = new BatteryArrayModel(struct_length);
            for (int i = 0; i < 3; i++)
            {
                devices.ReadClass(address_struct, batteryArray);
                BatteryDataModel batteryData = new BatteryDataModel();
                if (batteryArray.Batterys[0].ID != 0)
                {
                    batteryData.SnowflakeId = batteryArray.Batterys[0].ID;
                    batteryData.Data_PLC = batteryArray.Batterys[0].Data_PLC;
                    batteryData.Index = (byte)(1);
                    batteryData.Address_Struct = address_struct;
                    return (false, batteryData);
                }
                if (i == 2 && batteryData.SnowflakeId == 0)
                {
                    WriteCMD(1, devices, alarm_address);
                }
                Thread.Sleep(500);
            }
            return new(true, default);
        }

        public static (bool, List<BatteryDataModel>) ReadErinnerungen2(OmronCIP devices, string address_struct, int struct_length, string alarm_address, string method)
        {

            bool isID = true;
            List<BatteryDataModel> batteryDatas = new List<BatteryDataModel>();
            try
            {
                
              
                for (int j = 0; j < struct_length; j++)
                {
                    BatteryDataModel batteryArray = new BatteryDataModel();
                    devices.ReadClass($"{address_struct}[{j}]", batteryArray);
                    if (batteryArray.SnowflakeId != 0)
                    {
                        isID = false;
                    }

                    batteryDatas.Add(batteryArray);
                }
                //if (batteryDatas.Count > 0)
                //{
                //    return new(isID, batteryDatas);
                //}
            }
            catch (Exception e)
            {
                //RunLog($"读取记忆异常：{e}");
            }
            return new(isID, batteryDatas);
        }

        public double? GetWeiging(Models.Devices.DeviceClientModel device, string barcode)
        {
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Restart();
            double? before_weighing = null, after_weighing = null;
            while (stopwatch.ElapsedMilliseconds < _systemConfig.SCM.WeighingTimeout)
            {
                before_weighing = device.Communication.ReadSingle<double>(0, 0);
                if (before_weighing != null)
                {
                    RunLog($"-[{device.Index}] 条码：{barcode} 获取到重量 ==> {before_weighing} g");
                    if (after_weighing != null)
                    {
                        double difference = Math.Round((double)(before_weighing - after_weighing), 1, MidpointRounding.AwayFromZero);
                        if (difference >= -0.3 && difference <= 0.3)
                        {
                            RunLog($"-[{device.Index}] 获取到的稳定值 ==> {before_weighing} g");
                            stopwatch.Stop();
                            return before_weighing;
                        }
                    }
                    after_weighing = before_weighing;
                }
                Thread.Sleep(500);
            }
            stopwatch.Stop();
            return default;
        }
        /// <summary>
        /// 进站
        /// </summary>
        /// <param name="preventionCheckInterface"></param>
        /// <param name="getByProductCodeInterface"></param>
        /// <param name="entity"></param>
        /// <returns></returns>
        public ResultTypes BatteryInputDataUpload(IMESInteraction preventionCheckInterface, IMESInteraction getByProductCodeInterface, ProductionData entity)
        {
            Dictionary<string, object> param = new Dictionary<string, object>
            {
                { "machineNo", _parameterStatic.CollectionItemsParameter.EquipNum },
                { "producttype", _parameterStatic.CollectionItemsParameter.ProductType.ToString() },

                { "parameter", new Dictionary<string, object>()
                    {
                        { "tenantID", _parameterStatic.CollectionItemsParameter.ProductionLineNo },//产线编号
                        { "technicsProcessCode", _parameterStatic.CollectionItemsParameter.TechnicsProcessCode },//工序编码
                        { "equipCode", _parameterStatic.CollectionItemsParameter.EquipNum },//设备编号
                        { "productCodeList", new List<Dictionary<string, string>>
                            {
                                new Dictionary<string, string> { {"productCode", entity.BarCode } }
                            }
                        },//电芯条码                                            
                    }
                },
            };
            //在制品投料防呆校验接口
            entity.ResultScanCodeBefore = preventionCheckInterface.Interaction(_parameterStatic.MESParameter.BaseUrl + _parameterStatic.MESParameter.PreventionCheckRouter,
                 _parameterStatic.MESParameter.PreventionCheckTime,
                 _parameterStatic.MESParameter.PreventionCheckNumber,
                 DateTime.Now, new ProductionData[] { entity }, param);
            //if (resultTypes == ResultTypes.MES_停机)
            //{
            //    //写入MES停机信号
            //    WriteCMD(1, plc.Communication, _systemConfig.IAddress.MES_Shutdown);
            //}

            #region 工单获取,另外调用
            //if (entity.ResultScanCodeBefore == ResultTypes.合格)
            //{
            //    try
            //    {
            //        param.Remove("parameter");
            //        param.Add("parameter", new Dictionary<string, object>()
            //        {
            //            { "tenantID", _parameterStatic.CollectionItemsParameter.ProductionLineNo },//产线编号
            //            { "technicsProcessCode", _parameterStatic.CollectionItemsParameter.TechnicsProcessCode },//工序编码 
            //            { "productCode", entity.BarCode },//电芯条码                                            
            //        });

            //        //工单获取
            //       entity.ResultScanCodeBefore =
            //            getByProductCodeInterface.Interaction(_parameterStatic.MESParameter.BaseUrl + _parameterStatic.MESParameter.GetByProductCodeRoute,
            //            _parameterStatic.MESParameter.GetByProductCodeTime,
            //            _parameterStatic.MESParameter.GetByProductCodeNumber,
            //            DateTime.Now, new ProductionData[] { entity }, param);

            //        if (entity.ResultScanCodeBefore == ResultTypes.合格)
            //        {
            //            var WorkOrdersDictionary = param["result"] as List<Dictionary<string, object>>;

            //            RunLog($"{JsonSerializer.Serialize(WorkOrdersDictionary, HttpHelper.Options)}");

            //            if(WorkOrdersDictionary.Any())
            //            {
            //                entity.WorkOrderNumber = WorkOrdersDictionary[0]["produceOrderCode"].ToString();
            //                RunLog($"电芯：{entity.BarCode} 工单获取成功：{entity.WorkOrderNumber}");
            //            }
            //            //_parameterStatic.CollectionItemsParameter.WorkOrdersCollection.Clear();
            //            ////解析返回的代码
            //            //foreach (var item in param["result"] as List<Dictionary<string, object>>)
            //            //{
            //            //    _parameterStatic.CollectionItemsParameter.WorkOrdersCollection.Add(item["produceOrderCode"]?.ToString());
            //            //}
            //            //if (_parameterStatic.CollectionItemsParameter.WorkOrdersCollection.Count > 0)
            //            //{
            //            //    entity.WorkOrderNumber = _parameterStatic.CollectionItemsParameter.WorkOrdersCollection[0];
            //            //}
            //        }
            //    }catch(Exception ex)
            //    {
            //        RunLog($"66666666666{ex}");
            //    }


            //}
            #endregion


            if (entity.ResultScanCodeBefore != ResultTypes.合格 && entity.ResultTotal == ResultTypes._)
                entity.ResultTotal = entity.ResultScanCodeBefore;
            try
            {
                entity.Update();
            }
            catch (Exception ex)
            {
                RunLog($"-[{entity.LocationScanCodeBefore}] [{entity.BarCode}] 数据库保存异常：{ex}");
            }

            return entity.ResultScanCodeBefore;
        }

        /// <summary>
        /// 工单调用
        /// </summary>
        /// <param name="getByProductCodeInterface"></param>
        /// <param name="entity"></param>
        /// <returns></returns>
        public ResultTypes GetByProductCode(IMESInteraction getByProductCodeInterface, ProductionData entity)
        {
            #region 工单获取,另外调用

            Dictionary<string, object> param = new Dictionary<string, object>
            {
                { "machineNo", _parameterStatic.CollectionItemsParameter.EquipNum },
                { "producttype", _parameterStatic.CollectionItemsParameter.ProductType.ToString() },

                { "parameter", new Dictionary<string, object>()
                    {
                        { "tenantID", _parameterStatic.CollectionItemsParameter.ProductionLineNo },//产线编号
                        { "technicsProcessCode", _parameterStatic.CollectionItemsParameter.TechnicsProcessCode },//工序编码
                        { "equipCode", _parameterStatic.CollectionItemsParameter.EquipNum },//设备编号
                        { "productCodeList", new List<Dictionary<string, string>>
                            {
                                new Dictionary<string, string> { {"productCode", entity.BarCode } }
                            }
                        },//电芯条码                                            
                    }
                },
            };

            try
            {
                param.Remove("parameter");
                param.Add("parameter", new Dictionary<string, object>()
                    {
                        { "tenantID", _parameterStatic.CollectionItemsParameter.ProductionLineNo },//产线编号
                        { "technicsProcessCode", _parameterStatic.CollectionItemsParameter.TechnicsProcessCode },//工序编码 
                        { "productCode", entity.BarCode },//电芯条码                                            
                    });

                //工单获取
                entity.ResultScanCodeBefore =
                     getByProductCodeInterface.Interaction(_parameterStatic.MESParameter.BaseUrl + _parameterStatic.MESParameter.GetByProductCodeRoute,
                     _parameterStatic.MESParameter.GetByProductCodeTime,
                     _parameterStatic.MESParameter.GetByProductCodeNumber,
                     DateTime.Now, new ProductionData[] { entity }, param);

                if (entity.ResultScanCodeBefore == ResultTypes.合格)
                {
                    var WorkOrdersDictionary = param["result"] as List<Dictionary<string, object>>;

                    RunLog($"{JsonSerializer.Serialize(WorkOrdersDictionary, HttpHelper.Options)}");

                    if (WorkOrdersDictionary.Any())
                    {
                        entity.WorkOrderNumber = WorkOrdersDictionary[0]["produceOrderCode"].ToString();
                        RunLog($"电芯：{entity.BarCode} 工单获取成功：{entity.WorkOrderNumber}");
                    }
                    //_parameterStatic.CollectionItemsParameter.WorkOrdersCollection.Clear();
                    ////解析返回的代码
                    //foreach (var item in param["result"] as List<Dictionary<string, object>>)
                    //{
                    //    _parameterStatic.CollectionItemsParameter.WorkOrdersCollection.Add(item["produceOrderCode"]?.ToString());
                    //}
                    //if (_parameterStatic.CollectionItemsParameter.WorkOrdersCollection.Count > 0)
                    //{
                    //    entity.WorkOrderNumber = _parameterStatic.CollectionItemsParameter.WorkOrdersCollection[0];
                    //}
                }
            }
            catch (Exception ex)
            {
                RunLog($"66666666666{ex}");
            }

            return entity.ResultScanCodeBefore;

            #endregion
        }

        /// <summary>
        /// 电池出站上传数据
        /// </summary>
        /// <param name = "interaction" > 接口对象 </ param >
        /// < param name="production">电池数据</param>
        /// <returns></returns>
        public ResultTypes BatteryOutboundDataUpload(IMESInteraction interaction, ProductionData production, bool isOK = true, string ngType = "")
        {
            //string workOrderNumber = production.BarCode.Substring(12, 18);
            if (_temporaryStatic.MinuteProduction < 99999)
                Interlocked.Increment(ref _temporaryStatic.MinuteProduction); //一分钟产量
            if (string.IsNullOrEmpty(production.BatchElectrolyte))
                production.BatchElectrolyte = _parameterStatic.CollectionItemsParameter.BatchElectrolyte;
            Dictionary<string, object> parameter = new Dictionary<string, object>
            {
                //{ "produceOrderCode",workOrderNumber},//生产工单编码
                { "produceOrderCode",string.IsNullOrEmpty( production.WorkOrderNumber)? _parameterStatic.CollectionItemsParameter.WorkOrder:production.WorkOrderNumber},//生产工单编码
                { "technicsProcessCode",_parameterStatic.CollectionItemsParameter.TechnicsProcessCode },//工序编码 
                { "technicsProcessName",_parameterStatic.CollectionItemsParameter.TechnicsProcessName },//工序名称
                { "technicsStepCode",_parameterStatic.CollectionItemsParameter.TechnicsStepCode },//工步编码 
                { "technicsStepName",_parameterStatic.CollectionItemsParameter.TechnicsStepName },//工步名称 
                { "productCode",production.BarCode },//产品编码（模组） 
                { "productCount", 1},//产品数量 
                { "productQuality", isOK?1:0},//产品质量(结果判定)：0 不合格；1 合格；
                { "ngType", ngType},//NG时必填
                { "produceDate", DateTime.Now.ToString("yyyy-MM-dd")},//生产日期
                { "startTime", production.TimeScanCodeBefore.GetDateTime().ToString("yyyy-MM-dd HH:mm:ss")},//生产开始时间
                { "endTime", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")},//生产结束时间
                { "userName", _temporaryStatic.Mes_AccountName},//用户名称
                { "userAccount", _temporaryStatic.Mes_Account},//用户账号
                { "deviceCode", _parameterStatic.CollectionItemsParameter.EquipNum},//设备编码
                { "deviceName", _parameterStatic.CollectionItemsParameter.EquipName},//设备名称
                { "remarks", ""},//备注 
                { "tenantID", _parameterStatic.CollectionItemsParameter.ProductionLineNo },//产线编号
                { "produceInEntityList", new List< Dictionary<string, object>>
                    {
                        new Dictionary<string, object>
                        {
                            {"productCode", production.BarCode },
                            {"productCount", 1 }
                        },
                        new Dictionary<string, object>
                        {
                            {"productCode", production.BatchElectrolyte },
                            {"productCount", production.ActualTotalInjectionVolume <0 ? 0:production.ActualTotalInjectionVolume }
                        }
                    }
                },//产品编码（原材料）
            };

            //添加mes参数
            if (_mesParameterStatic.MesOutputParameters != null && _mesParameterStatic.MesOutputParameters.Count > 0)
            {
                // var propertyInfos = production.GetType().GetProperties();
                var produceInEntityList = new List<Dictionary<string, object>>();
                foreach (var item in _mesParameterStatic.MesOutputParameters)
                {
                    var valueType = GetTypeByStringHelper.GetTypeByString(item.DataType);
                    if (item.Description == null || string.IsNullOrEmpty(item.Description) ||
                        item.PropertyName == null || string.IsNullOrEmpty(item.PropertyName))
                    {
                        produceInEntityList.Add(new Dictionary<string, object>
                            {
                                {"productCode", production.BarCode },//产品编码
                                {"technicsParamName", item.TechnicsParamName },//工艺参数名称
                                {"technicsParamCode", item.TechnicsParamCode },//工艺参数编码
                                {"technicsParamValue", Activator.CreateInstance(valueType)},//工艺参数值
                                {"technicsParamQuality", isOK?"1":"0" },//工艺参数质量(结果判定)：0 不合格；1 合格；
                                {"desc", 1 },//工艺参数质量(结果判定)：0 不合格；1 合格；
                            });
                    }
                    else
                    {
                        var propertyInfo = production.GetType().GetProperty(item.PropertyName, BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);
                        //var ret = propertyInfos.Where(x => x.Name == item.PropertyName).FirstOrDefault();                       
                        if (propertyInfo != null) //如果电池中有此参数
                        {
                            var value = propertyInfo.GetValue(production, null);
                            var technicsParamValue = valueType == propertyInfo.PropertyType ? value : GetTypeByStringHelper.TryTypeConvert(valueType, value, propertyInfo.Name);
                            produceInEntityList.Add(new Dictionary<string, object>
                            {
                                {"productCode", production.BarCode },//产品编码
                                {"technicsParamName", item.TechnicsParamName },//工艺参数名称
                                {"technicsParamCode", item.TechnicsParamCode },//工艺参数编码
                                {"technicsParamValue", technicsParamValue},//工艺参数值
                                {"technicsParamQuality", isOK?"1":"0" },//工艺参数质量(结果判定)：0 不合格；1 合格；
                                {"desc", 1 },//工艺参数质量(结果判定)：0 不合格；1 合格；
                            });
                        }

                    }

                }
                parameter.TryAdd("produceParamEntityList", produceInEntityList);
            }

            Dictionary<string, object> valuePairs = new Dictionary<string, object>()
            {
                { "machineNo", _parameterStatic.CollectionItemsParameter.EquipNum },
                { "producttype", _parameterStatic.CollectionItemsParameter.ProductType.ToString() },
                { "parameter", parameter},
            };
            //if (isOK)
            //{
            production.ResultOutput = interaction.Interaction(_parameterStatic.MESParameter.BaseUrl + _parameterStatic.MESParameter.OpenAddRouter,
                _parameterStatic.MESParameter.OpenAddTime,
                _parameterStatic.MESParameter.OpenAddNumber,
                DateTime.Now, new ProductionData[] { production }, valuePairs);
            //}
            //else
            //{
            //    interaction.Interaction(_parameterStatic.MESParameter.BaseUrl + _parameterStatic.MESParameter.OpenAddRouter,
            //        _parameterStatic.MESParameter.OpenAddTime,
            //        _parameterStatic.MESParameter.OpenAddNumber,
            //        DateTime.Now, new ProductionData[] { production }, valuePairs);
            //    production.ResultOutput = ResultTypes.不合格;
            //}
            production.TimeOutput = DateTime.Now.GetJSTimeUtc();

            if (production.ResultTotal == ResultTypes._)
                production.ResultTotal = production.ResultOutput;//整个电池完成          

            try
            {
                DateTime createTime = production.TimeScanCodeBefore.GetDateTime();
                ProductionData.Meta.TableName = $"ProductionData_{createTime:yyyy}{createTime.GetQuarterly()}";
                production.Update();
            }
            catch (Exception ex)
            {
                RunLog($"更新出站MES数据异常：{ex}");
            }

            return production.ResultOutput;
        }

        public string DBSuffix => _systemConfig.SCM.MainDeviceType == MainDeviceTypeEnum.一次注液 ? "One" : "Two";

        /// <summary>
        /// 前称重范围检查
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        protected ResultTypes BeforeWeightRange_Check(ProductionData entity)
        {
            if (!_parameterStatic.DecideParameter.EnableBeforeInjection)
            {
                RunLog($"请注意!!![{entity.BarCode}] 未启用前称重检查==>>强制合格");
                return ResultTypes.合格;
            }
            string[] range = entity.RangeForeweigh.Split('-');
            double down = Convert.ToDouble(range[0]);
            double up = Convert.ToDouble(range[1]);
            return entity.FormerWeighing switch
            {
                var k when k <= up && k >= down => ResultTypes.合格,
                var k when k > up => ResultTypes.称重偏重,
                var k when k < down => ResultTypes.称重偏轻,
                _ => ResultTypes.不合格,
            };
        }
        /// <summary>
        /// 后称重范围检查
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        protected ResultTypes AfterWeightRange_Check(ProductionData entity)
        {
            if (!_parameterStatic.DecideParameter.EnableAfterInjection)
            {
                RunLog($"请注意!!![{entity.BarCode}] 未启用后称重检查==>>强制合格");
                return ResultTypes.合格;
            }
            string[] range = entity.RangeAfterWeighing.Split('-');
            double down = Convert.ToDouble(range[0]);
            double up = Convert.ToDouble(range[1]);
            return entity.AfterWeighing switch
            {
                var k when k <= up && k >= down => ResultTypes.合格,
                var k when k > up => ResultTypes.称重偏重,
                var k when k < down => ResultTypes.称重偏轻,
                _ => ResultTypes.不合格,
            };
        }
        /// <summary>
        /// 注液量范围检查
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        protected ResultTypes InjectionVolRange_Check(ProductionData entity)
        { 
            string[] range = entity.RangeFluidRate.Split('-');
            RunLog($"{entity.BarCode}当前保液量范围：{range}");
            double down = Convert.ToDouble(range[0]);

            double up = Convert.ToDouble(range[2]);
            return entity.ActualTotalInjectionVolume switch
            {
                var k when k <= up && k >= down => ResultTypes.合格,
                var k when k > up => ResultTypes.注液量偏多,
                var k when k < down => ResultTypes.注液量偏少,
                _ => ResultTypes.不合格,
            };
        } 


    }
}
